package com.wangc.study.reflect;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

/**
 * @author wangC
 * @create 2020-05-26 下午10:38
 * @Description
 **/
public class ReflectClassAPI {


    //API 使用
    public static void main(String[] args) throws Exception {

        Class<?> clazz = Class.forName("com.wangc.study.reflect.Student");
        //获取成员变量,包括子类和父类，同时只能包含公共的方法
        Field[] fields = clazz.getFields();
        for (Field field : fields) {
            System.out.println(field);
            System.out.println(field.getName());
            System.out.println(field.getType());
            System.out.println(field.getModifiers()); //返回访问修饰符的常量  public=1
            System.out.println("---------------------");
        }

        System.out.println("=======================");
        //此方法返回的是当前类的所有属性。不仅仅局限于公共访问修饰符，所有的访问修饰符都可以拿到
        Field[] declaredFields = clazz.getDeclaredFields();
        for (Field declaredField : declaredFields) {
            System.out.println(declaredField.getName());
        }

        System.out.println("=======================");
        /**
         * java.lang.InstantiationException
         * 这个异常多半是由于通过反射在实例化的时候，对应的类里面覆盖了无参构造而导致无法实例化，
         * 由于创建类的时候，默认有一个无参构造，前提是没有其他构造方法，如果没有明确的将无参构造写出来，该类就是缺少无参构造了，也就导致了无法实例化
         */
        //反射在一定程度上破坏了封装性，需要合理使用
        Field address = clazz.getDeclaredField("address");
        address.setAccessible(true);//设置该属性能否被访问，true表示能被访问，破坏了封装性
        System.out.println(address.getName());
        Object o = clazz.newInstance();
        address.set(o,"aaa");
        System.out.println(((Student)o).getAddress());

        System.out.println("===============================");
        //获取该对象的普通方法
        //包含的方法范围是当前对象及父类对象的所有公共方法
        Method[] methods = clazz.getMethods();
        for (Method method : methods) {
            //System.out.println(method);
            System.out.println(method.getName());
            //System.out.println(method.getModifiers());
        }

        //获取当前类中所有的方法，无论什么访问修饰符
        Method[] declaredMethods = clazz.getDeclaredMethods();
        for (Method declaredMethod : declaredMethods) {
            System.out.println(declaredMethod.getName());
        }

        System.out.println("-----------------------");
        Method add = clazz.getDeclaredMethod("add", int.class, int.class);
        add.setAccessible(true);
        add.invoke(o, 1, 2);

        System.out.println("----------------------");
        //获取对象的所有构造方法，只能获取公有的改造方法
        Constructor<?>[] constructors = clazz.getConstructors();
        for (Constructor<?> constructor : constructors) {
            System.out.println(constructor.getName());

        }

        //获取所有的构造方法，私有和公有
        Constructor<?>[] declaredConstructors = clazz.getDeclaredConstructors();
        for (Constructor<?> declaredConstructor : declaredConstructors) {
            System.out.println(declaredConstructor.getName());
        }

        //获取私有的构造方法
        Constructor<?> declaredConstructor = clazz.getDeclaredConstructor(String.class, int.class, String.class);
        declaredConstructor.setAccessible(true);
        Student o1 = (Student)declaredConstructor.newInstance("asd", 11, "wang");
        System.out.println(o1);
    }

}
